Linguaggio di programmazione C
Fu ideato nei Bell Laboratories della AT&T nel 1972 da Dennis Ritchie come evoluzione del linguaggio B di Ken Thompson, usato per la scrittura dei primi sistemi operativi UNIX. Lo stesso Thompson nel 1970 si era a sua volta ispirato al linguaggio BCPL di Martin Richards, pensato per scrivere sistemi operativi e software di sistema.
Il C viene classificato come linguaggio ad alto livello: la scrittura delle istruzioni, quindi, è indipendente dall'architettura del calcolatore su cui le istruzioni saranno eseguite. Il grande successo del C è dovuto a diversi fattori: prima di tutto, la felice scelta del modo di astrazione dall'hardware, che pur essendo del tutto logico e generico rimane molto vicino all'hardware stesso: il linguaggio C si basa su poche istruzioni chiave molto semplici, che spesso (come gli operatori di autoincremento, autodecremento e aritmetici con assegnazione) ricalcano l'assembly delle CPU e sono traducibili direttamente con una singola istruzione di linguaggio macchina; riserva un ruolo centrale al concetto di puntatore, che viene generalizzato fino a concidere con l'indirizzamento indiretto, un modo di accedere alla memoria hardware caratteristico di tutte le moderne CPU. Questo rende il C un linguaggio particolarmente efficiente. D'altra parte, rispetto al linguaggio assembly, il C ha in più una struttura logica definita e leggibile, funzioni in stile Pascal e soprattutto il controllo sui tipi, che manca completamente in assembly.
Inoltre la grammatica e la sintassi del C sono molto libere e flessibili, permettendo di scrivere istruzioni complesse e potenti in poche righe di codice (ma anche istruzioni assolutamente criptiche e illeggibili). In definitiva, il successo del C fu decretato dall'essere un linguaggio creato da programmatori esperti, per essere usato da programmatori esperti.
Questa grande libertà, la complessità sintattica del linguaggio (che, come abbiamo visto, contiene poche istruzioni di base) e il ruolo centrale dei puntatori, che è necessario usare praticamente fin dai primi programmi, ne fanno viceversa un linguaggio ostico e sconsigliabile ai neofiti, che cadono quasi subito in una serie di trappole che, se pure ovvie per un esperto, sono molto difficili da individuare ad un occhio inesperto.
Grazie alla particolare efficienza del codice prodotto dai sui compilatori, il C venne utilizzato per riscrivere la maggior parte del codice del sistema UNIX, riducendo l'uso dell'assembly ad un piccolo gruppo di funzioni. La sua importanza tuttavia, crebbe solo dopo il 1978 con la pubblicazione da parte di Brian Kernighan e Dennis Ritchie del libro The C Programming Language, nel quale il linguaggio venne definito in modo preciso.
Il suo successivo larghissimo utilizzo portò alla nascita di diversi dialetti e quindi alla necessità di definirne uno standard, realizzatosi nel 1983 con la versione ANSI (American National Standards Institute) del C. Prendendo spunto da questa versione definitiva, e unendo al C l'uso delle classi di Simula, Bjarne Stroustrup iniziò a sviluppare il C++.
Lo standard attuale del linguaggio è stato definito dall'International Standard Organization (ISO) nel 1999, ed è noto come ISO C99 (codice ISO 9899).
Storia dell'evoluzione
- Il primo sviluppo del linguaggio C ebbe inizio nei laboratori AT&T Bell Labs tra il 1969 e il 1973; secondo Dennis Ritchie, il periodo più creativo fu il 1972. Fu chiamato C, perché molte delle sue caratteristiche derivavano del precedente linguaggio B. Questa è la voce più accreditata, ma esistono anche altre voci fantasiose meno accreditate, come C per l'iniziale di Compiler, oppure di Cat l'animale preferito di Ritchie.
Esistono, inoltre, alcune simpatiche leggende metropolitane riguardanti C e il suo sistema operativo imparentato, Unix:
- Lo sviluppo del C fu il risultato del desiderio dei programmatori di avere un gioco tipo Asteroids. Giocavano sul mainframe della loro compagnia, che stava per essere dimesso, e c'erano circa cento giocatori incalliti, tra cui Thompson e Ritchie, che scoprirono di non aver sufficiente controllo della navicella per evitare gli asteroidi. Di conseguenza, decisero di fare il porting sul PDP-7 libero nel ufficio. Ma non esisteva il sistema operativo e quindi dovettero scriverne uno. Con il tempo, decisero di fare anche il porting per il PDP-11, ma questo fu molto più oneroso perché tutto il codice doveva essere scritto assembly. Provarono ad utilizzare il linguaggio ad alto livello B, ma non supportava le funzionalità avanzate del PDP-11, e da qui nacque il linguaggio C.
- La motivazione della creazione del primo calcolatore, che venne utilizzato per sviluppare UNIX, fu la necessità di possedere un sistema per automatizzare il processo dei brevetti. La versione primordiale di UNIX fu, dunque, sviluppata in linguaggio assembly. Più tardi, fu usato il linguaggio C per riscrivere e migliorare l'intero sistema operativo.
Dal 1973, il linguaggio C era diventato sufficientemente potente per essere utilizzato nei kernel UNIX e la maggior parte di essi, in origine scritti in linguaggio assembly PDP-11/20, furono riscritti in C. Questi furono tra i primi kernel di sistemi operativi implementati in linguaggio più recente dell'assembly. Gli unici precedenti sono il sistema Multics scritto in PL/I; TRIPOS e AmigaOS in BCPL.
- Nel 1978, Dennis Ritchie e Braian Kernighan pubblicarono la loro prima edizione del libro The C Programming Language. Questo libro, noto tra i programmatori come K&R, venne utilizzato per molti anni come specifica informale del linguaggio. La versione della C che si descrive, viene comunemente chiamata come K&R C.
Immagine della copertina del noto libro The C Programming Language di Brian Kernighan e Dennis Ritchie pubblicato nel 1978. La prima edizione venne utilizzata, per molti anni, come supporto per le specifiche del linguaggio C.
La seconda edizione del libro copre lo standard successivo ANSI C di cui tratterà il successivo punto 3.
K&R introdussero le seguenti nuove caratteristiche al linguaggio:
- tipo di dato:
- struct
- long int
- unsigned int
- sintassi: gli operatori del tipo =+ vennero cambiati in +=, poiché =+ confondeva l'analizzatore del lessico del compilatore: infatti, per esempio, f =+ 7 veniva comparato a f = +7 e non a f = f + 7.
Si è ritenuto che K&R C sia la parte più fondamentale del linguaggio che è necessaria a supportare un compilatore C. Per molti anni, perfino dopo l'introduzione di ANSI C, venne considerato il minimo comun denominatore, che i programmatori C seguono per avere la massima portabilità, ed un codice lecito anche su compilatori che non supportano completamente ANSI C.
In queste prime versioni di C, le funzioni che ritornano un valore non del tipo integer devono essere definite o dichiarate, tramite un apposito enunciato, prima che vengano utilizzate. Una funzione utilizzata senza alcuna dichiarazione, viene assunto che debba restituire un valore del tipo integer. Il tipo di parametri passato ad una funzione non viene controllato, sebbene alcuni compilatori segnalino, con un messaggio di errore, se una funzione viene chiamata con un numero differente di argomenti.
Negli anni successivi alla pubblicazione di K&R C, molte caratteristiche non ufficiali vennero aggiunte al linguaggio, supportate inizialmente solo dai compilatori AT&T. Ecco le principali:
- funzioni del tipo void e, di conseguenza, il tipo di dato void
- possibilità che una funzione ritorni il tipo di dato struct o union
- i nomi di campo di uno struct in uno spazio di nome separato per ogni tipo di struct
- assegnamento per il tipo di dato struct
- l'attributo const per rendere un oggetto solamente leggibile
- una libreria standard comprendente la maggior parte delle funzionalità implementate dai vari fornitori
- enumerazione
- il tipo di dato float a precisione singola
- Verso la fine degli anni '70, il C cominciò a rimpiazzare il BASIC come principale linguaggio di programmazione di microcomputer.
Verso la fine degli anni '80, venne adottato l'uso con gli IBM PC, e la sua popolarità aumentò significativamente. Nello stesso periodo, Bjarne Stroustup presso i laboratori Bell iniziò a lavorare all'aggiunta di construtti di programmazione orientata agli oggetti per il C. Il nuovo linguaggio che nascerà, chiamato C++, è molto comune nelle applicazioni che girano sul sistema operativo Windows; il C, però rimane il più diffuso nel mondo Unix. Un altro linguaggio sviluppato in questo periodo è Objective-C che aggiunge, anch'esso, programmazione orientata agli oggetti al C. Oggi, viene usato per sviluppare applicazioni Cocoa in ambiente Mac OS X anche se non è popolare quanto il C++.
Nel 1983, l' American National Standards Institute (ANSI) formò un comitato, X3J11, per stabilire le specifiche standard del C. Dopo un lungo ed arduo processo, lo standard fu conpletato nel 1989 e classificato come ANSI X3.159-1989 Programming Language C. Questa versiona del linguaggio è spesso chiamata più semplicemente ANSI C. Nel 1990, l'ANSI C, con alcune piccole modifiche, venne adottato dal' International Organization for Standardization (ISO) con il nome di ISO/IEC 9899:1990.
Uno degli scopi del processo di standardizzazione dell' ANSI C era di fornire una versione di K&R C che incorporasse anche tutte le caratteristiche non ufficiali successivamente introdotte. Tuttavia, il comitato di normalizzazione ha scelto, inoltre, di includere parecchie nuove caratteristiche, quali i prototipi di funzione (presi dal C++) e un preprocessore con maggiori capacità.
L'ANSI C è, oggi, supportato da quasi tutti i compilatori più diffusi. La maggior parte del codice C che viene scritto ai giorni nostri è basato su ANSI C. L'esecuzione di ogni programma scritto interamente in standard C è garantita su qualsiasi piattaforma con un'implementazione conforme al C. Nonostante ciò, molti programmi che vengono scritti in ANSI C, verranno compilati solo in un certo ambiente (o su una certa piattaforma o solo su un certo compilatore) a causa dell'uso di librerie non standard, o perché alcuni compilatori non aderisco allo standard ANSI C o ai suoi successori, o poiché sono basati sull'esatta dimensione di certi tipi di dato su una particolare piattaforma.
-
Dopo il processo di standardizzazione dell'ANSI, le specifiche del linguaggio C rimasero relativamente statiche per un certo periodo, mentre il C++ continuava ad evolversi. Solo nel 1995 con Normative Amendment 1 venne definita una nuova versione del linguaggio C, ma questa versione non ebbe successo e, raramente, è conosciuta nel mondo dalla programmazione.
Solo nel ultimi anni 90, lo standard venne sottoposto ad una revisione, che portò alla pubblicazione ISO 9899:1999 nel 1999. A questo standard, solitamente, ci si riferisce con la sigla C99. Nel Marzo 2000, il C99 venne adottato dell'ANSI come standard.
Le nuove caratteristiche del C99 sono:
- allineamento di funzioni
- le dichiarazioni delle variabili possono essere collocate ovunque (come in C++). Prima, erano consentite una di seguito all'altra e all'inizio dell'enunciato di composizione
- nuovi tipi di dato inclusi long, long int, boolean, complex
- lunghezza variabile di array
- introduzione del commento di una linea con // (preso dal C++) che molti compilatori C supportavano già come estensione
- nuove librerie di funzioni come snprintf()
- nuovi header file come stdint.h
Gli interessi nel supporto delle nuove funzionalità del C99 sono contrapposti. Ne consegue che da un lato, GCC (GNU Compiler Collection) e tanti altri compilatori supportano, oggi, la maggior parte delle novità introdotte; dall'altro i compilatori proprietari mantenuti da Microsoft e da Borland non supportano queste funzionalità e non sembrano interessati ad aggiungerle, neppure in futuro.